package ekahau.positioning.client.ui.navigator;

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Vector;

import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Sash;
import org.eclipse.ui.part.ViewPart;
import org.w3c.dom.TypeInfo;
import org.w3c.dom.events.EventTarget;

import com.ekahau.common.sdk.EStreamConnection;

import ekahau.positioning.client.model.EkahauPositionEngineClient;
import ekahau.positioning.client.model.EkahauTag;
import ekahau.positioning.client.model.IModelChanged;
import ekahau.positioning.client.model.EkahauTag.EVENT_TYPE;
import ekahau.positioning.client.ui.imageviewer.IUserSelectionChangeListener;
import ekahau.positioning.services.providor.ServicesClientRequest.ZONE_TYPE;
import ekahau.positioning.services.providor.ServicesClientResponse;
import ekahau.positioning.services.providor.client.ServicesClient;
import ekahau.positioning.services.providor.server.ServicesProvidor;
import ekahau.ue.registration.IAreaUpdate;
import ekahau.ue.registration.IPreferenceManager;
import ekahau.ue.registration.RegisteredClientResponse;
import ekahau.ue.registration.RegistrationClientRequest;
import ekahau.ue.registration.RegistrationClientRequest.PREFERENCE_TYPE;
import ekahau.ue.registration.server.UERegistrationListener;
import ekahau.ue.registration.server.UERegistrationServer;

public class NavigationView extends ViewPart implements IModelChanged, IPreferenceManager {

	public static final String ID = "LTUClient.navigationView";
	private IUserSelectionChangeListener userSelectionListener ;
	private Vector<TagInfo> infoList = new Vector<TagInfo>();
	private EkahauPositionEngineClient client;
	private ServicesProvidor servicesProvider ;
	
	private HashMap<TagInfo , Vector<Point>> trackerDB  = 
								new HashMap<NavigationView.TagInfo, Vector<Point>>();
	
	private HashMap<String , PREFERENCE_TYPE> preferences = new HashMap<String, PREFERENCE_TYPE>();
	private List list;
	private List servicesList;
	boolean byZone = true;
	private StyledText styledTex;
	private UERegistrationServer ueRegistrationServer ;
	public class TagInfo{
		
		private String name ;
		private long id;
		private Point point;
		private String address;
		private int zoneId; 
		private String zoneName;
		private EVENT_TYPE eType;
		
		
		public TagInfo(String name, long id, 
							Point p, String macAddress, String zoneName, int zoneId, EVENT_TYPE type){
			this.name = name;
			this.id = id;
			point = p;
			address = macAddress;
			this.zoneName = zoneName;
			eType = type;
		}
		
		public String getName(){
			return name;
		}
		public String getZoneName(){
			return zoneName;
		}
		
		public void setEventType(EVENT_TYPE type){
			eType = type;;
		}
		
		public String getEventType(){
			
			if(EVENT_TYPE.LOCAION_CHANED == eType)
				return "Location Changed";
			else if(EVENT_TYPE.NEW_ZONE_ENTERED == eType)
				return "Entered into a new Zone";
			else if(EVENT_TYPE.ZONE_EXITED == eType)
				return "Noze Exited";
			
			else 
				return "No Event";
		}
		public EVENT_TYPE getEventTypeInt(){
			return eType;
		}
		public String getMacAddress(){
			return address;
		}
		public long getID(){
			return id;
		}
		
		public Point getPoint(){
			return point;
		}
		public void setPoint(Point p){
			point = p;
		}
		public String toString(){
			return "Name:    " + name + "\n" + "DeviceID:  " + id + "\n" + "MAC_Address:  " 
			          + address + "\n" + "ZoneID:    " + zoneId + "\n"  + "ZoneName:    " + zoneName +
			          "\n"  + point + "\n" + "Event Type:" + getEventType();
			
		}
		public void setZoneNameID(String zName, int id){
			zoneName = zName;
			zoneId = id;
		}
	}
 	/**
     * This is a callback that will allow us to create the viewer and initialize
     * it.
     */
	public void createPartControl(Composite parent) {
          
		final Composite shell = new Composite(parent, SWT.NONE);
		shell.setLayoutData(new GridData(GridData.FILL_BOTH));
		Collection<EkahauTag> lisTags = null;
		client = new EkahauPositionEngineClient();
		
		client.addModelChangedListener(this);
		ueRegistrationServer = new UERegistrationServer(this);
		ueRegistrationServer.start();
		lisTags = client.getTags() ;
		try{
			for (Iterator iterator = lisTags.iterator(); iterator.hasNext();) {
				EkahauTag ekahauTag = (EkahauTag) iterator.next();
				TagInfo info = new TagInfo(ekahauTag.getName(), ekahauTag.getDeviceId(),
													new Point(ekahauTag.getX(), ekahauTag.getY()), ekahauTag.getAddress(), 
													ekahauTag.getZoneName(), ekahauTag.getZoneId(), EVENT_TYPE.NONE);
				
				infoList.add(info);
				Vector<Point> v = new Vector<Point>();
				v.add(new Point(info.getPoint().x, info.getPoint().y));
				trackerDB.put(info, v);
				preferences.put(info.getMacAddress(), PREFERENCE_TYPE.ALL);
			
			}
		}catch(Exception e){
			e.printStackTrace();
		}	
		final Sash sash = new Sash (shell, SWT.HORIZONTAL);
		styledTex = new StyledText(shell, SWT.V_SCROLL | SWT.H_SCROLL);
		styledTex.setText ("");
		styledTex.setEditable(false);
		final FormLayout form = new FormLayout ();
		shell.setLayout (form);
		
		FormData listData = new FormData ();
		/*button1Data.left = new FormAttachment (0, 0);
		button1Data.right = new FormAttachment (sash, 0);
		button1Data.top = new FormAttachment (0, 0);
		button1Data.bottom = new FormAttachment (100, 0);
		button1.setLayoutData (button1Data); */
		
		listData.left = new FormAttachment (0, 0);
		listData.right = new FormAttachment (100, 0);
		listData.top = new FormAttachment (0, 0);
		listData.bottom = new FormAttachment (sash, 0);
		
		Composite group = new Composite(shell, SWT.HORIZONTAL | SWT.H_SCROLL | SWT.V_SCROLL);
		group.setLayoutData (listData);
		org.eclipse.swt.layout.GridLayout gLayout = new org.eclipse.swt.layout.GridLayout();
		gLayout.verticalSpacing = 2;
		group.setLayout(gLayout);
		
		org.eclipse.swt.widgets.Label label = new org.eclipse.swt.widgets.Label(group, SWT.LEFT| SWT.WRAP);
		label.setText("Tag List:");
		label.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_WHITE));
		GridData data = new GridData(GridData.FILL_HORIZONTAL);
		data.heightHint = 20;
		label.setLayoutData(data);
		
		list = new List(group, SWT.V_SCROLL | SWT.H_SCROLL | SWT.FILL);
		//list.setLayoutData (listData);
		list.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL));
		list.addSelectionListener(new SelectionListener() {
			
			@Override
			public void widgetSelected(SelectionEvent e) {
				// TODO Auto-generated method stub
				System.out.println(e);
				Display.getDefault().asyncExec(new Runnable() {
					
					@Override
					public void run() {
						int index = list.getSelectionIndex();
						if (index <= -1) {
							return;
						}
						
						if(list.getItem(list.getSelectionIndex()).compareToIgnoreCase("All") == 0){
							Vector<Point> vList[] = new Vector[infoList.size()];
							for (int i = 0; i < vList.length; i++) {
								vList[i] = trackerDB.get(infoList.get(i));
							}
							
							userSelectionListener.navigatorSelectionChanged(infoList.toArray(new TagInfo[infoList.size()]), vList);
							styledTex.setText("");
							servicesList.removeAll();
						}else{
						
							TagInfo tInfo = infoList.elementAt(index);
							userSelectionListener.navigatorSelectionChanged(infoList.elementAt(index), 
														trackerDB.get(infoList.get(list.getSelectionIndex())));
							styledTex.setText(infoList.elementAt(index).toString());
							
							String sList[] = updateServicesList(tInfo.getZoneName(), preferences.get(tInfo.getMacAddress()));
							
							if(sList == null)
				            	return;
							servicesList.removeAll();
							servicesList.setItems(sList);
						}
						
					}
				}) ;
			}
			
			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
				// TODO Auto-generated method stub
				
			}
		});
		
		//init services list
		Label label1 = new Label(group, SWT.LEFT| SWT.WRAP| SWT.FILL);
		label1.setText("Restaurants List:");
		label1.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_WHITE));
		data = new GridData(GridData.FILL_HORIZONTAL);
		data.heightHint = 20;
		label1.setLayoutData(data);
		
		servicesList = new List(group, SWT.V_SCROLL | SWT.H_SCROLL);
		servicesList.setLayoutData(new GridData(GridData.FILL_HORIZONTAL |GridData.FILL_BOTH));
		
		//init Tag list
		for (Iterator iterator = infoList.iterator(); iterator.hasNext();) {
				
				TagInfo type = (TagInfo) iterator.next();
				list.add(type.getName());
				
		}	
		list.add("All");
		final int limit = 20, percent = 70;
		final FormData sashData = new FormData ();
		/*sashData.left = new FormAttachment (percent, 0);
		sashData.top = new FormAttachment (0, 0);
		sashData.bottom = new FormAttachment (100, 0);*/
		
		sashData.left = new FormAttachment (0, 0);
		sashData.right = new FormAttachment (100, 0);
		sashData.bottom = new FormAttachment (percent, 0);
		
		
		sash.setLayoutData (sashData);
		sash.addListener (SWT.Selection, new Listener () {
			public void handleEvent (Event e) {
				Rectangle sashRect = sash.getBounds ();
				Rectangle shellRect = shell.getClientArea ();
				int right = shellRect.height - sashRect.height - limit;
				e.x = Math.max (Math.min (e.x, right), limit);
				if (e.x != sashRect.x)  {
					sashData.left = new FormAttachment (0, e.x);
					shell.layout ();
				}
			}
		});
		
		FormData textData = new FormData ();
		/*button2Data.left = new FormAttachment (sash, 0);
		button2Data.right = new FormAttachment (100, 0);
		button2Data.top = new FormAttachment (0, 0);
		button2Data.bottom = new FormAttachment (100, 0); */
		
		textData.left = new FormAttachment (0, 0);
		textData.right = new FormAttachment (100, 0);
		textData.top = new FormAttachment (sash, 0);
		textData.bottom = new FormAttachment (100, 0); 
		
		styledTex.setLayoutData (textData);
		
		servicesProvider = new ServicesProvidor(this) ;
		servicesProvider.start() ;
	}
	
	
	
	/**
	 * Passing the focus request to the viewer's control.
	 */
	public void setFocus() {
		//viewer.getControl().setFocus();
	}

	public void setSelectionListener(IUserSelectionChangeListener listener) {
		userSelectionListener = listener;
	}



	@Override
	public void modelChanged(final EkahauTag tag) {
		
		Display.getDefault().asyncExec(new Runnable() {
			
			@Override
			public void run() {
				for (Iterator iterator = infoList.iterator(); iterator.hasNext();) {
					
					TagInfo type = (TagInfo) iterator.next();
					if(tag.getAddress().compareTo(type.getMacAddress()) == 0){
						
						type.setEventType(tag.getEventType());
						type.getPoint().x = tag.getX();
						type.getPoint().y = tag.getY();
						type.setZoneNameID(tag.getZoneName(), tag.getZoneId());
						if(type.getEventTypeInt() == EVENT_TYPE.LOCAION_CHANED){
							
							Vector<Point> v = trackerDB.get(type);
							v.add(new Point(tag.getX(), tag.getY()));
						
							if(list.getItem(list.getSelectionIndex()).compareToIgnoreCase("All") == 0){
								Vector<Point> vList[] = new Vector[infoList.size()];
								for (int i = 0; i < vList.length; i++) {
									vList[i] = trackerDB.get(infoList.get(i));
								}
								
								userSelectionListener.navigatorSelectionChanged(infoList.toArray(new TagInfo[infoList.size()]), vList);
								styledTex.setText("");
								servicesList.removeAll();
								
							}else if(list.getSelectionIndex() >= 0 && 
										type.getMacAddress().compareToIgnoreCase(
													infoList.get(list.getSelectionIndex()).getMacAddress()) == 0){
								userSelectionListener.navigatorSelectionChanged(type, v);
								styledTex.setText(type.toString());
								servicesList.removeAll();
								
								try{
									String serList [] = updateServicesList(type.getZoneName(), 
											preferences.get(type.getMacAddress()));
									//Send a response to clients who are registered as listener for any zone change
									ueRegistrationServer.notifyAreaChanged(type.getMacAddress(), tag.getZoneName(),serList);
									servicesList.setItems(serList);
									
								}catch(Exception e){
									
								}
								
								
							}
							
						}
						break;
					}
					
				}
				
			}
				
		});
	}
	
	public void updatePreferences(String macID, PREFERENCE_TYPE pType){
		
		preferences.put(macID, pType);
		
	}

	public String[] updateServicesList(String zoneName, PREFERENCE_TYPE pType) {
		
		String resList[] = new String[0];
		ServicesClientResponse resInfo = null;
		
		if(zoneName != null && zoneName.compareToIgnoreCase("zone1") == 0)
			resInfo = ServicesClient.getServiceInfo(pType, ZONE_TYPE.ZONE_1);
		else if(zoneName != null && zoneName.compareToIgnoreCase("zone2") == 0)
			resInfo = ServicesClient.getServiceInfo(pType, ZONE_TYPE.ZONE_2);
		else if(zoneName != null && zoneName.compareToIgnoreCase("zone3") == 0)
			resInfo = ServicesClient.getServiceInfo(pType, ZONE_TYPE.ZONE_3);
		else if(zoneName != null && zoneName.compareToIgnoreCase("zone4") == 0)
			resInfo = ServicesClient.getServiceInfo(pType, ZONE_TYPE.ZONE_4);
		else if(zoneName != null && zoneName.compareToIgnoreCase("room1") == 0)
			resInfo = ServicesClient.getServiceInfo(pType, ZONE_TYPE.ROOM_1);
		else if(zoneName != null && zoneName.compareToIgnoreCase("room2") == 0)
			resInfo = ServicesClient.getServiceInfo(pType, ZONE_TYPE.ROOM_2);
		else if(zoneName != null && zoneName.compareToIgnoreCase("room3") == 0)
			resInfo = ServicesClient.getServiceInfo(pType, ZONE_TYPE.ROOM_3);
		else if(zoneName != null && zoneName.compareToIgnoreCase("room4") == 0)
			resInfo = ServicesClient.getServiceInfo(pType, ZONE_TYPE.ROOM_4);
		else if(zoneName != null && zoneName.compareToIgnoreCase("c1") == 0)
			resInfo = ServicesClient.getServiceInfo(pType, ZONE_TYPE.C_1);
		else if(zoneName != null && zoneName.compareToIgnoreCase("c2") == 0)
			resInfo = ServicesClient.getServiceInfo(pType, ZONE_TYPE.C_2);
		else if(zoneName != null && zoneName.compareToIgnoreCase("c3") == 0)
			resInfo = ServicesClient.getServiceInfo(pType, ZONE_TYPE.C_3);
		else
			resInfo = ServicesClient.getServiceInfo(pType, ZONE_TYPE.NONE);
		
		if(resInfo != null){
			
			resList = resInfo.getInfo();
		
		}	
		if(resList == null){
        	System.out.println("Sring Null");
        	resList = new String[0];
		}
		return resList;
	}

	class MyRunnable implements Runnable{
		
		String slist[] = new String[0];
		String macID = null;
		public MyRunnable(String lis[], String macID){
			slist = lis;
			this.macID = macID;
		}
		@Override
		public void run() {
            
			if(slist == null )
            	return;
            
            if(list.getSelectionIndex() >= 0 && 
            			list.getItem(list.getSelectionIndex()).compareToIgnoreCase("All") == 0){
            	servicesList.removeAll();
				//servicesList.setItems(new String[0]);
            	
            }else if(macID != null && list.getSelectionIndex() >= 0 && 
					macID.compareToIgnoreCase(
								infoList.get(list.getSelectionIndex()).getMacAddress()) == 0){
				servicesList.removeAll();
				servicesList.setItems(slist);
            }
			
			
		}
	};

	@Override
	synchronized public RegisteredClientResponse processPreferenceRequest(
			final RegistrationClientRequest request) {
		
		final RegisteredClientResponse response = new RegisteredClientResponse(new String[0], "");
		// TODO Auto-generated method stub
		preferences.put(request.getUserID(),request.getPreferenceType());
		
		for (Iterator iterator = infoList.iterator(); iterator.hasNext();) {
			TagInfo tag = (TagInfo) iterator.next();
			
			if(tag.getMacAddress() != null && tag.getMacAddress().compareToIgnoreCase(request.getUserID()) == 0){
				String res[] = updateServicesList(tag.getZoneName(), request.getPreferenceType());
				response.setInfo(res);
				response.setZoneName(tag.getZoneName());
				try{
					Display.getDefault().syncExec(new MyRunnable(res, request.getUserID()));
				}catch(Exception e){
					
				}
			}
		}
		
		return response;
	}


    public TagInfo getTagInfo(String id){
    	
    	for (Iterator iterator = infoList.iterator(); iterator.hasNext();) {
			TagInfo tag = (TagInfo) iterator.next();
			
			if(tag.getMacAddress() != null && tag.getMacAddress().compareToIgnoreCase(id) == 0){
				
				return tag; 
				
			}
    	}
    	
    	return null;
    }
	@Override
	public void addAreaChangeListener(IAreaUpdate aCListener) {
		// TODO Auto-generated method stub
		
	}
}